class JiraMapping
{
    mapping()
    {
        return {};
    }

    hasFunc(funcName, self)
    {
        if (!self) {
            self = this;
        }
        return '[object Function]'===Object.prototype.toString.call(self[funcName])
    }

    getValue(funcName, origData, self)
    {
        if (!self) {
            self = this;
        }

        if (self.hasFunc(funcName, self)) {
            return self[funcName](origData);
        }
        return origData;
    }

    convert(issueObject)
    {
        let self = this;
        let mapping = this.mapping();

        let fields = {};

        Object.keys(mapping).forEach(function(sourceField) {
            fields = self.getFields(fields, mapping, issueObject, sourceField, self);
        });

        fields = this.afterConvert(fields);

        return {
            fields: fields
        };
    }

    getFields(fields, currentMapping, currentObject, sourceField, self)
    {
        // if mapping field value is object
        let targetField = currentMapping[sourceField];

        if ('[object Object]'===Object.prototype.toString.call(currentMapping[sourceField])) {
            Object.keys(currentMapping[sourceField]).forEach(function(currentSourceField){
                fields = self.getFields(fields, currentMapping[sourceField], currentObject[sourceField], currentSourceField, self);
            });
        } else {
            // if has value
            // if has filed name's func
            if (currentObject[sourceField]) {
                switch(Object.prototype.toString.call(currentObject[sourceField])) {
                    case '[object String]':
                        fields[targetField] = currentObject[sourceField];
                    break;
                    case '[object Object]':
                        if (currentObject[sourceField].value) {
                            fields[targetField] = {value: self.getValue(sourceField, currentObject[sourceField].value, self)};
                        } else if (currentObject[sourceField].name) {
                            fields[targetField] = {name: self.getValue(sourceField, currentObject[sourceField].name, self)};
                        }
                    break;
                    case '[object Array]':
                        currentObject[sourceField].forEach(function(item, idx) {
                            if (!fields[targetField]) {
                                fields[targetField] = new Array();
                            }
                            if (item.value) {
                                fields[targetField][idx] = {value: self.getValue(sourceField, item.value, self)};
                            } else if (item.name) {
                                fields[targetField][idx] = {name: self.getValue(sourceField, item.name, self)};
                            }
                        });
                    break;
                }
            }
        }

        return fields;
    }

    afterConvert(fields)
    {
        return fields;
    }
}